bitkeeper revision 1.1159.1.451 (41a51866R21ReiS-WH2NSkl2MaBhaA)
authorcl349@arcadians.cl.cam.ac.uk <cl349@arcadians.cl.cam.ac.uk>
Wed, 24 Nov 2004 23:25:26 +0000 (23:25 +0000)
committercl349@arcadians.cl.cam.ac.uk <cl349@arcadians.cl.cam.ac.uk>
Wed, 24 Nov 2004 23:25:26 +0000 (23:25 +0000)
Add per exec_domain event_channel initialization.
Make sched_rem_domain/rem_task act on exec_domain.

xen/common/domain.c
xen/common/event_channel.c
xen/common/schedule.c
xen/include/xen/sched-if.h
xen/include/xen/sched.h

index 8f472d4bdf27b61f811782afb168411932fa5f8b..4d5dbdf33cc64b9e675949a7d2e98e0e6e3aaad3 100644 (file)
@@ -135,10 +135,13 @@ struct domain *find_last_domain(void)
 
 void domain_kill(struct domain *d)
 {
+    struct exec_domain *ed;
+
     domain_pause(d);
     if ( !test_and_set_bit(DF_DYING, &d->d_flags) )
     {
-        sched_rem_domain(d);
+        for_each_exec_domain(d, ed)
+            sched_rem_domain(ed);
         domain_relinquish_memory(d);
         put_domain(d);
     }
@@ -330,6 +333,9 @@ long do_boot_vcpu(unsigned long vcpu, full_execution_context_t *ctxt)
     atomic_set(&ed->pausecnt, 0);
     shadow_lock_init(ed);
 
+    if ( (rc = init_exec_domain_event_channels(ed)) != 0 )
+        goto out;
+
     memcpy(&ed->thread, &idle0_exec_domain.thread, sizeof(ed->thread));
 
     /* arch_do_createdomain */
@@ -337,8 +343,10 @@ long do_boot_vcpu(unsigned long vcpu, full_execution_context_t *ctxt)
 
     sched_add_domain(ed);
 
-    if ( (rc = arch_final_setup_guestos(ed, c)) != 0 )
+    if ( (rc = arch_final_setup_guestos(ed, c)) != 0 ) {
+        sched_rem_domain(ed);
         goto out;
+    }
 
     /* Set up the shared info structure. */
     update_dom_time(d);
index 5d4ac4d4ef38ebf2c40e2725670f6251cd4a3312..e9d331f2d974c7868b503985130c7f39160a073e 100644 (file)
@@ -48,8 +48,11 @@ static int get_free_port(struct exec_domain *ed)
     {
         if ( max == MAX_EVENT_CHANNELS )
             return -ENOSPC;
-        
-        max = port + EVENT_CHANNELS_SPREAD;
+
+        if ( port == 0 )
+            max = INIT_EVENT_CHANNELS;
+        else
+            max = port + EVENT_CHANNELS_SPREAD;
         
         chn = xmalloc(max * sizeof(event_channel_t));
         if ( unlikely(chn == NULL) )
@@ -256,7 +259,8 @@ static long evtchn_bind_virq(evtchn_bind_virq_t *bind)
      * bound yet. The exception is the 'misdirect VIRQ', which is permanently 
      * bound to port 0.
      */
-    if ( ((port = ed->virq_to_evtchn[virq]) != 0) ||
+    if ( ((port = ed->virq_to_evtchn[virq]) !=
+          (ed->eid * EVENT_CHANNELS_SPREAD)) ||
          (virq == VIRQ_MISDIRECT) ||
          ((port = get_free_port(ed)) < 0) )
         goto out;
@@ -357,7 +361,8 @@ static long __evtchn_close(struct domain *d1, int port1)
     chn1 = d1->event_channel;
 
     /* NB. Port 0 is special (VIRQ_MISDIRECT). Never let it be closed. */
-    if ( (port1 <= 0) || (port1 >= d1->max_event_channel) )
+    if ( (port1 <= 0) || (port1 >= d1->max_event_channel) ||
+         ((port1 & (EVENT_CHANNELS_SPREAD - 1)) == 0) )
     {
         rc = -EINVAL;
         goto out;
@@ -642,17 +647,31 @@ long do_event_channel_op(evtchn_op_t *uop)
 }
 
 
+int init_exec_domain_event_channels(struct exec_domain *ed)
+{
+    struct domain *d = ed->domain;
+    int port, ret = -EINVAL, virq;
+
+    spin_lock(&d->event_channel_lock);
+    port = ed->eid * EVENT_CHANNELS_SPREAD;
+    if ( ((port < d->max_event_channel &&
+           d->event_channel[port].state != ECS_FREE)) ||
+         (get_free_port(ed) != port) )
+        goto out;
+    d->event_channel[port].state  = ECS_VIRQ;
+    d->event_channel[port].u.virq = VIRQ_MISDIRECT;
+    for ( virq = 0; virq < NR_VIRQS; virq++ )
+        ed->virq_to_evtchn[virq] = port;
+    ret = 0;
+ out:
+    spin_unlock(&d->event_channel_lock);
+    return ret;
+}
+
 int init_event_channels(struct domain *d)
 {
     spin_lock_init(&d->event_channel_lock);
-    d->event_channel = xmalloc(INIT_EVENT_CHANNELS * sizeof(event_channel_t));
-    if ( unlikely(d->event_channel == NULL) )
-        return -ENOMEM;
-    d->max_event_channel = INIT_EVENT_CHANNELS;
-    memset(d->event_channel, 0, INIT_EVENT_CHANNELS * sizeof(event_channel_t));
-    d->event_channel[0].state  = ECS_VIRQ;
-    d->event_channel[0].u.virq = VIRQ_MISDIRECT;
-    return 0;
+    return init_exec_domain_event_channels(d->exec_domain[0]);
 }
 
 
index 0dd20dff9b26276b7f3877d77cf66e0f137be39d..acc21e2a357bf77afb4cc82159bbc31b7604d002 100644 (file)
@@ -191,14 +191,12 @@ void sched_add_domain(struct exec_domain *ed)
     TRACE_2D(TRC_SCHED_DOM_ADD, d->id, ed);
 }
 
-void sched_rem_domain(struct domain *d) 
+void sched_rem_domain(struct exec_domain *ed) 
 {
-    struct exec_domain *ed;
 
-    for_each_exec_domain(d, ed)
-        rem_ac_timer(&ed->timer);
-    SCHED_OP(rem_task, d);
-    TRACE_2D(TRC_SCHED_DOM_REM, d->id, d);
+    rem_ac_timer(&ed->timer);
+    SCHED_OP(rem_task, ed);
+    TRACE_3D(TRC_SCHED_DOM_REM, ed->domain->id, ed->eid, ed);
 }
 
 void init_idle_task(void)
index 0e6cd69d3b93c29a0ed584bb5d53cf9bb87c36d7..f73eace25b9d72a823a8f141252390158c1691c8 100644 (file)
@@ -40,7 +40,7 @@ struct scheduler
     int          (*alloc_task)     (struct exec_domain *);
     void         (*add_task)       (struct exec_domain *);
     void         (*free_task)      (struct domain *);
-    void         (*rem_task)       (struct domain *);
+    void         (*rem_task)       (struct exec_domain *);
     void         (*sleep)          (struct exec_domain *);
     void         (*wake)           (struct exec_domain *);
     void         (*do_block)       (struct exec_domain *);
index d69e3bf40efe67f8e76529ef6d81c8798f401daa..7a96a6a1fe7c8674c2508e45b5e4fff5ae80baf0 100644 (file)
@@ -56,6 +56,7 @@ typedef struct event_channel_st
 
 int  init_event_channels(struct domain *d);
 void destroy_event_channels(struct domain *d);
+int  init_exec_domain_event_channels(struct exec_domain *ed);
 
 struct exec_domain 
 {
@@ -233,8 +234,8 @@ extern unsigned long wait_init_idle;
 #define set_current_state(_s) do { current->state = (_s); } while (0)
 void scheduler_init(void);
 void schedulers_start(void);
-void sched_add_domain(struct exec_domain *d);
-void sched_rem_domain(struct domain *d);
+void sched_add_domain(struct exec_domain *);
+void sched_rem_domain(struct exec_domain *);
 long sched_ctl(struct sched_ctl_cmd *);
 long sched_adjdom(struct sched_adjdom_cmd *);
 int  sched_id();